# calibration_random_util.py
import csv
import re
from pathlib import Path
from typing import Tuple

from osc05.utils.random_util import RandomUtil
from osc05.static.constants import Constants


class CalibrationRandomUtil(RandomUtil):
    """专门用于样本量校准的 RandomUtil 子类"""

    def __init__(self, seed=1, samples_dir=None, n_sf=Constants.N_ACTIVITY,
                 sample_size=None, calibration_seed=None):
        super().__init__(seed, samples_dir, n_sf)

        self.sample_size = sample_size
        self.calibration_seed = calibration_seed

        # 为校准创建确定性的数据映射
        self._scenario_counter = 0

    def get_samples(self, reset: bool = False) -> Tuple[list[float], list[float], list[float], list[bool], list[bool]]:
        """重写get_samples方法，支持校准参数"""
        if reset:
            self._scenario_counter = 0

        # 计算当前场景的唯一标识
        if self.sample_size is not None and self.calibration_seed is not None:
            # 使用校准参数创建确定性映射
            unique_id = self._create_unique_scenario_id()
            result = self._get_deterministic_samples(unique_id)
        else:
            # 回退到父类的行为
            result = super().get_samples(reset)

        self._scenario_counter += 1
        return result

    def _create_unique_scenario_id(self):
        """为当前场景创建唯一标识"""
        # 组合所有参数创建唯一ID
        return hash(f"{self.sample_size}_{self.calibration_seed}_{self._scenario_counter}")

    def _get_deterministic_samples(self, unique_id):
        """根据唯一ID获取确定性的采样数据"""
        # 使用唯一ID选择LHS文件中的特定行
        file_line = abs(unique_id) % self._get_file_line_count()
        return self._read_specific_line(file_line)

    def _get_file_line_count(self):
        """获取LHS文件行数"""
        if not hasattr(self, '_cached_line_count'):
            try:
                with open(self.lhs_file, 'r', encoding='utf-8') as f:
                    self._cached_line_count = sum(1 for _ in f) - 1  # 减去表头
            except Exception as e:
                print(f"无法统计LHS文件行数: {e}")
                self._cached_line_count = 1000  # 默认值
        return self._cached_line_count

    def _read_specific_line(self, line_number):
        """读取LHS文件的特定行"""
        try:
            with open(self.lhs_file, 'r', encoding='utf-8') as f:
                reader = csv.reader(f)
                next(reader)  # 跳过表头

                for i, row in enumerate(reader):
                    if i == line_number:
                        return self._parse_row(row)

                # 如果行号超出范围，回到第一行
                f.seek(0)
                next(reader)
                first_row = next(reader)
                return self._parse_row(first_row)

        except Exception as e:
            print(f"读取LHS文件失败: {e}")
            # 回退到随机生成
            return self._generate_random_row()

    def _parse_row(self, row):
        """解析CSV行数据"""
        smp_durations = [float(x) for x in row[0:18]]
        smp_delivery_delay_days = [float(x) for x in row[18:36]]
        smp_crane_failure_times = self._parse_float_list(row[36])
        smp_rain_hold_daily_events = self._parse_bool_list(row[37])
        smp_strong_wind_hold_daily_events = self._parse_bool_list(row[38])

        return (
            smp_durations,
            smp_delivery_delay_days,
            smp_crane_failure_times,
            smp_rain_hold_daily_events,
            smp_strong_wind_hold_daily_events,
        )

    def _parse_float_list(self, cell: str):
        """解析浮点数列表"""
        cell = cell.strip().strip('"')
        if cell.startswith("[") and cell.endswith("]"):
            numbers = re.split(r"[\s,]+", cell[1:-1].strip())
            return [float(x) for x in numbers if x]
        else:
            return [float(cell)]

    def _parse_bool_list(self, cell: str):
        """解析布尔列表"""
        cell = cell.strip().strip('"')
        if cell.startswith("[") and cell.endswith("]"):
            tokens = re.split(r"[\s,]+", cell[1:-1].strip())
            return [t == "True" for t in tokens if t in ("True", "False")]
        else:
            return [cell in ("1", "True", "true")]

    def _generate_random_row(self):
        """生成随机数据行（回退方案）"""
        # 使用父类的随机生成逻辑
        durations = self._rng.triangular(
            Constants.STANDARD_FLOOR_ERECTION_LEFT,
            Constants.STANDARD_FLOOR_ERECTION_MODE,
            Constants.STANDARD_FLOOR_ERECTION_RIGHT,
            18
        )

        delivery_delays = self._rng.normal(
            Constants.COMPONENT_DELIVERY_DELAY_LOC,
            Constants.COMPONENT_DELIVERY_DELAY_SCALE,
            18
        )

        crane_failure = [self._rng.exponential(Constants.CRANE_MTTF)]
        rain_hold = [self._rng.random() > 0.9]
        wind_hold = [self._rng.random() > 0.95]

        # 转换为与LHS文件相同的格式
        row = (
                list(durations) +
                list(delivery_delays) +
                [str(crane_failure)] +
                [str(rain_hold)] +
                [str(wind_hold)]
        )

        return self._parse_row(row)